package com.xtecher.app.widget;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by Luhao on 2017/2/26.
 */

public class ZoomRecyclerView extends RecyclerView {

    private static final String TAG = "Zoom";
    //    用于记录下拉位置
    private float y = 0f;
    //    zoomView原本的宽高
    private int zoomViewWidth = 0;
    private int zoomViewHeight = 0;

    //    是否正在放大
    private boolean mScaling = false;

    //设置下拉距离触发刷新事件
    private int refreshDis = 250;

    public void setRefreshDistance(int refreshDis) {
        this.refreshDis = refreshDis;
    }

    //    放大的view，默认为null
    private View zoomView = null;
    private OnSlideUpListener onSlideUpListener;
    private boolean isRefresh = false;

    public void setZoomView(View zoomView) {
        this.zoomView = zoomView;
    }

    //    滑动放大系数，系数越大，滑动时放大程度越大
    private float mScaleRatio = 0.6f;

    public void setmScaleRatio(float mScaleRatio) {
        this.mScaleRatio = mScaleRatio;
    }

    //    最大的放大倍数
    private float mScaleTimes = 2f;

    public void setmScaleTimes(int mScaleTimes) {
        this.mScaleTimes = mScaleTimes;
    }

    //    回弹时间系数，系数越小，回弹越快
    private float mReplyRatio = 0.5f;

    public void setmReplyRatio(float mReplyRatio) {
        this.mReplyRatio = mReplyRatio;
    }

    public ZoomRecyclerView(Context context) {
        super(context);
    }

    public ZoomRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public ZoomRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
//        不可过度滚动，否则上移后下拉会出现部分空白的情况
        setOverScrollMode(OVER_SCROLL_NEVER);

    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        if (zoomView == null) {
            return super.onTouchEvent(ev);
        }

        if (zoomViewWidth <= 0 || zoomViewHeight <= 0) {
            zoomViewWidth = zoomView.getMeasuredWidth();
            zoomViewHeight = zoomView.getMeasuredHeight();
        }
        if (zoomViewWidth <= 0 || zoomViewHeight <= 0) {
            return super.onTouchEvent(ev);
        }

        switch (ev.getAction()) {
            case MotionEvent.ACTION_MOVE:
                if (computeVerticalScrollOffset() == 0 && onSlideUpListener != null) {
                    onSlideUpListener.onTop(zoomView);
                }
                if (!mScaling) {
                    if (computeVerticalScrollOffset() == 0) {
                        y = ev.getY();//滑动到顶部时，记录位置
                        isRefresh = false;
                    } else {
                        break;
                    }
                }
                int distance = (int) ((ev.getY() - y) * mScaleRatio);
                if (distance < 0) {
                    if (onSlideUpListener != null) {
                        onSlideUpListener.onSlideUp(zoomView);
                    }
                    break;//若往下滑动
                }
                mScaling = true;
                setZoom(distance);
                Log.d(TAG, "onTouchEvent: " + distance);
                return true;
            case MotionEvent.ACTION_UP:
                mScaling = false;
                replyView();
                break;
        }
        return super.onTouchEvent(ev);
    }

    public void setOnSlideUpListener(OnSlideUpListener onSlideUpListener) {
        this.onSlideUpListener = onSlideUpListener;
    }

    /**
     * 下拉放大后上拉覆盖需要实现接口
     */
    public interface OnSlideUpListener {

        /**
         * 当上滑时做的操作
         *
         * @param view
         */
        void onSlideUp(View view);

        /**
         * 当在顶部时做的操作
         *
         * @param view
         */
        void onTop(View view);

        /**
         * 下拉刷新集成
         */
        void onRefresh();
    }

    /**
     * 放大view
     */
    private void setZoom(float s) {
        float scaleTimes = (float) ((zoomViewWidth + s) / (zoomViewWidth * 1.0));
//        如超过最大放大倍数，直接返回
        if (scaleTimes > mScaleTimes) return;
        if (s > refreshDis && onSlideUpListener != null && !isRefresh) {
            isRefresh = true;
            onSlideUpListener.onRefresh();
        }
        ViewGroup.LayoutParams layoutParams = zoomView.getLayoutParams();
        layoutParams.width = (int) (zoomViewWidth + s);
        layoutParams.height = (int) (zoomViewHeight * ((zoomViewWidth + s) / zoomViewWidth));
//        设置控件水平居中
        ((MarginLayoutParams) layoutParams).setMargins(-(layoutParams.width - zoomViewWidth) / 4, 0, -(layoutParams.width - zoomViewWidth) / 4, 0);
        zoomView.setLayoutParams(layoutParams);
    }

    /**
     * 回弹
     */
    private void replyView() {
        final float distance = zoomView.getMeasuredWidth() - zoomViewWidth;
        // 设置动画
        ValueAnimator anim = ObjectAnimator.ofFloat(distance, 0.0F).setDuration((long) (distance * mReplyRatio));
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                setZoom((Float) animation.getAnimatedValue());
            }
        });
        anim.start();
    }
}
